コンポーネントをキャッシュする
- 2012 年 4月 9 日
前回から引き続きリリース済みのiOSアプリ、漢字の練習帳の動作を軽量化していく検証。
今回は「選んで練習」のボタン表示を改善したい。この画面は最初80字しかない一年生を作った時はこんなものかなと思っていたのだけど、200字ほどの他の学年では長く感じる。
実際に表示するまでにどの位時間がかかっているのかを計測してみる。
インスタンスの生成直前と表示直後の時間を取得し差を測ってみた。
この画面ではフレームレート24で、1フレームあたり20個ボタンを生成してます。
検証は漢字の練習帳 六年生でしているのでボタンの数は181個。
ということはボタンを全部表示するのに10フーレム必要なわけだから、理屈上は最短でも、1秒÷24フレーム×10フレーム = 0.41666666…秒かかるはず。
これを5回試した。
まず、現状の結果がこれ。
time: 0.663
time: 0.577
time: 0.567
time: 0.572
time: 0.624
これはADL上の結果ですけどそれでも0.1秒位遅れてるぽい。といってもこれがまんま実機で出るなら別に気にしない。
実機だとこれの10倍近く遅れているような印象なので、遅っ!って感じ。
以前作ったアプリで「ひらがなれんしゅうちょう」はFlashからAIR2.0で画面密度も標準で作っている(当時、標準しか無かった。)のだけど、同じような画面でボタン約90個を表示していても気にならないレベルで表示される。単純に比較出来ないとしても遅いのはたぶんFlexコンポーネントのせい。コンポーネントは汎用性がある分処理のオーバーヘッドが大きくなっているので。
でもコンポーネントをやめてオリジナルなボタンを作るとかは避けたい。パフォーマンスはそのほうが断然良くなる可能性あるけど、フレームワークに守られている良さというか、たとえばここではスクロールがあるけどコンポーネントを使っているなら何も気にせずボタンを配置するだけでいい。
だけどオリジナルにボタンを作るならスクロール用のキャンセルを入れたりとか必要な実装が増えていって、フレームワークを使う意義がなくなっていってしまう。なので現状の仕組みで出来る限りの方法をとる。
ここのボタンのスキンは高解像度用と標準用を作っていて、しかもiPhoneをだけをターゲットにしたアプリなのでサイズは結局のところ固定のままだ。
なのでスキンクラスやコンポーネントから主にサイズなどを演算している処理をオーバーライドして消したみた。主に弄ったのは、
drawBackground measure drawMinimumHitArea layoutContents updateDisplayList |
このあたりのメソッドを可能な場合はオーバーライドして何もしないようにした。
これでもう一度タイムを計測してみると、
time: 0.591
time: 0.503
time: 0.527
time: 0.497
time: 0.504
個人的にもっと速くなるんじゃないかと思っていたので若干残念だったのだけど若干は速くなったみたい。
さらに何か出来ないかと考えキャッシュさせることにした。Viewが切り替わる度にボタンの生成・破棄をしているので、一度生成したボタンは消えないようにキャッシュして再利用してみる。メモリの使用量は増えるけど「生成」のコストがなくなるはず。
これでさらにもう一度タイムを計測した結果が、
time: 0.604
time: 0.418
time: 0.43
time: 0.417
time: 0.417
お、今度は1回目が遅いものの(キャッシュしていないので)、その後は全体的に速い。0.417っていうのは理論上の最短に近い。
それでも実機ではそれなりに時間がかかってしまうので、それをカバーする為に見た目上、先にボタンが表示されるようにした。いわゆる遅延ロードみたいなやつ。修正前はボタンがすべて生成されてから表示していましたが、1フレーム毎に生成している段階で画面に表示し操作できるように変更。一番下のボタンを操作するには結局最後まで待たなきゃいけないし、全体の表示までのトータルの時間では画面の更新がない分、修正前のほうが速いのだけど、ずっとビジーインジケーターだけが表示されるより印象として速く感じる。
ということで、この方法を使うことにしました。
精査して次回のアップデートに入れますのでお待ちください。